//
//  MSVideoPlayerView.m
//  MSPhotoBrowser
//
//  Created by zzg on 2021/8/30.
//

#import "MSVideoPlayerView.h"
#import "MSVideoPlayerLayerView.h"
#import "MSVideoBottomBar.h"
#import "MSVideoProgressView.h"
#import "MSMaterialDesignSpinner.h"
#import <Masonry/Masonry.h>


@interface MSVideoPlayerView()<UIGestureRecognizerDelegate,MSVideoBottomBarDelegate>

@property (nonatomic, strong) NSURL *videoURL;                                  // 视频URL
@property (nonatomic, strong) AVPlayer *player;                                 // 播放器
@property (nonatomic, strong) AVPlayerItem *playerItem;                         // 播放器Item
@property (nonatomic, strong) NSObject *playbackTimeObserver;                   // 监控播放进度观察者
@property (nonatomic, strong) MSVideoPlayerLayerView * playerLayerView;       // 视频显示的范围视图
@property (nonatomic, strong) UIView * touchView;                               // 点击触控视图 控制底部和上部视图展示
@property (nonatomic, strong) UIButton * cancelButton;                          // 取消按钮
@property(nonatomic, strong) UIButton * downloadButton;
@property (nonatomic, strong) UIButton * middlePlayButton;                      // 中间播放按钮

@property (nonatomic, assign) CGFloat videoDuration;                            // 视频总时长
@property (nonatomic, assign) BOOL isDragingSlider;                             // 是否是拖拽状态
@property (nonatomic, assign) BOOL isVideoCanPlay;                              // 视频是否可以播放状态
@property (nonatomic ,assign) BOOL previousSeekPlayStatus;                      // 滑动seek之前的播放状态

@property (nonatomic, strong) MSVideoBottomBar *bottomBar;                    // 底部黑色背景及进度条及播放暂停按钮
@property (nonatomic, strong) UIView * tMSarView;                              // 顶部黑色背景图
@property (nonatomic, strong) MSVideoProgressView * downloadProgress;         // 视频下载进度视图
@property (nonatomic, assign) CGFloat  currentPlayTime;                         // 当前播放的时间点,用于解决seektime后，每次播放会往前回退的bug
@property (nonatomic, strong) MSMaterialDesignSpinner * videoLoadingIndicator;  // 加载指示


@end


@implementation MSVideoPlayerView
- (void)dealloc {
    [self destroyPlayer];
}

- (instancetype)initWithFrame:(CGRect)frame andVideoURL:(NSURL *)videoURL andAutoPlay:(BOOL)autoPlay{
    self = [super initWithFrame:frame];
    if (self) {
        _videoURL = videoURL;
//        [MSVideoHelper sharedHelper].delegate = self;
        [self setupSubViews];
        [self configTheSubViewsHidenOrShow];
        if (autoPlay) {
            [self setupPlayer];
        }
    }
    return self;
}

#pragma mark - Lazy Load
- (MSVideoPlayerLayerView *)playerLayerView {
    if (!_playerLayerView) {
        _playerLayerView = [[MSVideoPlayerLayerView alloc] init];
    }
    return _playerLayerView;
}

- (MSVideoBottomBar *)bottomBar {
    if (!_bottomBar) {
        _bottomBar = [MSVideoBottomBar videoTMSar];
        _bottomBar.delegate = self;
    }
    return _bottomBar;
}

- (UIButton *)middlePlayButton
{
    if (!_middlePlayButton) {
        _middlePlayButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [_middlePlayButton setImage:[UIImage imageNamed:@"video_big_play"] forState:UIControlStateNormal];
//        _middlePlayButton.backgroundColor = [UIColor redColor];
        [_middlePlayButton addTarget:self action:@selector(repeatPlayButtonClick) forControlEvents:UIControlEventTouchUpInside];
    }
    return _middlePlayButton;
}

- (UIView *)touchView {
    if (!_touchView) {
        _touchView = [[UIView alloc] init];
        _touchView.backgroundColor = [UIColor clearColor];
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(touchViewTapAction:)];
        tap.delegate = self;
        [_touchView addGestureRecognizer:tap];
    }
    return _touchView;
}

- (UIButton *)cancelButton {
    if (!_cancelButton) {
        _cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
        _cancelButton.showsTouchWhenHighlighted = YES;
        [_cancelButton setImage:[UIImage imageNamed:@"video_close"] forState:UIControlStateNormal];
        [_cancelButton addTarget:self action:@selector(cancelTheVideo) forControlEvents:UIControlEventTouchUpInside];
//        [_cancelButton setMS_hitTestEdgeInsets:UIEdgeInsetsMake(-10, -10, -10, -10)];
    }
    return _cancelButton;
}

- (UIButton *)downloadButton {
    if (!_downloadButton) {
        _downloadButton = [UIButton buttonWithType:UIButtonTypeCustom];
        _downloadButton.showsTouchWhenHighlighted = YES;
        [_downloadButton setTitle:@"保存" forState:UIControlStateNormal];

        _downloadButton.layer.cornerRadius = 25 *0.5;
        _downloadButton.layer.masksToBounds = YES;
        /**
                _downloadButton.backgroundColor = LDRGBCOLOR(95, 95, 95);
        _downloadButton.titleLabel.font = [UIFont ldFontWithFamilyName:LDFontStyleRegular fontSize:14];
         */
        [_downloadButton addTarget:self action:@selector(downloadTheVideo) forControlEvents:UIControlEventTouchUpInside];
    }
    return _downloadButton;
}



- (UIView *)tMSarView {
    if (!_tMSarView) {
        _tMSarView = [[UIView alloc]init];
//        if (kMS_IS_IPHONEX_LATER) {
//            // iphonex
//            _tMSarView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:1];
//        }else {
            _tMSarView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.65];
//        }
    }
    return _tMSarView;
}

- (MSVideoProgressView *)downloadProgress {
    if (!_downloadProgress) {
        _downloadProgress = [[MSVideoProgressView alloc]init];
        _downloadProgress.drawColor = [UIColor whiteColor];
        _downloadProgress.backgroundColor = [UIColor clearColor];
        _downloadProgress.layer.borderColor = [UIColor whiteColor].CGColor;
        _downloadProgress.layer.borderWidth = 1;
    }
    return _downloadProgress;
}

- (MSMaterialDesignSpinner *)videoLoadingIndicator
{
    if (!_videoLoadingIndicator ) {
        _videoLoadingIndicator = [[MSMaterialDesignSpinner alloc]init];
        _videoLoadingIndicator.lineWidth = 2;
        _videoLoadingIndicator.duration  = 1.5;
        _videoLoadingIndicator.hidesWhenStopped = YES;
        _videoLoadingIndicator.tintColor = [[UIColor whiteColor] colorWithAlphaComponent:0.9];
    }
    return _videoLoadingIndicator;
}

// 设置界面
- (void)setupSubViews {
    __weak typeof(self) weakSelf = self;
    [self addSubview:self.playerLayerView];
    [self.playerLayerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.bottom.right.mas_equalTo(0);
    }];
    
    [self addSubview:self.touchView];
    [self.touchView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.equalTo(weakSelf.playerLayerView);
        make.top.equalTo(weakSelf.playerLayerView).offset(44);
        make.bottom.equalTo(weakSelf.playerLayerView).offset(-44);
    }];
    
    
    [self addSubview:self.tMSarView];
    CGFloat tMSarHeight;
    /*
    if (IPHONE_X) {
        tMSarHeight = 64 + 24;
    }else {
        tMSarHeight = 64;
    }
     */
    tMSarHeight = 64;
    [self.tMSarView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(weakSelf.playerLayerView);
        make.height.mas_equalTo(tMSarHeight);
        make.left.mas_equalTo(0);
        make.width.mas_equalTo(weakSelf.mas_width);
    }];
    
    [self.tMSarView addSubview:self.cancelButton];
    [self.cancelButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(15);
        make.bottom.mas_equalTo(-15);
    }];
    
    [self.tMSarView addSubview:self.downloadButton];
    [self.downloadButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.mas_equalTo(-15);
        make.bottom.mas_equalTo(-15);
        make.size.mas_equalTo(CGSizeMake(65, 25));
    }];
    
    
    [self addSubview:self.bottomBar];
    CGFloat bottomBarHeight = 49;
    [self.bottomBar mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.mas_equalTo(0);
        /*
        make.bottom.mas_equalTo(weakSelf.playerLayerView.bottom).offset(-LDSafeBottomHeight);
         */
        make.height.mas_equalTo(bottomBarHeight);
    }];
    
    [self addSubview:self.middlePlayButton];
    [self.middlePlayButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.mas_equalTo(self);
        make.centerY.mas_equalTo(self);
        make.size.mas_equalTo(CGSizeMake(64, 64));
    }];

    [self addSubview:self.downloadProgress];
    [self.downloadProgress mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.mas_equalTo(self);
        make.centerY.mas_equalTo(self);
        make.size.mas_equalTo(weakSelf.middlePlayButton);
        weakSelf.downloadProgress.layer.cornerRadius = 32;
    }];
    [self bringSubviewToFront:self.downloadProgress];
    
    [self addSubview:self.videoLoadingIndicator];
    [self.videoLoadingIndicator mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self);
        make.width.with.height.mas_equalTo(50);
    }];
}

//  控制初始化时 主要子视图的显示或隐藏及其他初始化
- (void)configTheSubViewsHidenOrShow {
    self.middlePlayButton.hidden = NO;
    self.downloadProgress.hidden = YES;
    self.downloadProgress.progress = 0;
    [self.videoLoadingIndicator stopAnimating];
//    [self hideBottomAndTopTool];
    [self.bottomBar resetTheBottomView];
    _isVideoCanPlay = NO;
    self.playerState = MSVideoPlayerStateFailed;      ///  初始的时候，都是失败状态
}

// 设置视频播放相关
- (void)setupPlayer {
    _playerLayerView.hidden = NO;
    _playerItem = [AVPlayerItem playerItemWithURL:_videoURL];
    _player = [AVPlayer playerWithPlayerItem:_playerItem];
    [(AVPlayerLayer *)self.playerLayerView.layer setPlayer:_player];
    [_playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    [_playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
    [_playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
    [_playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemDidPlayToEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:_playerItem];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive) name:UIApplicationWillResignActiveNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
    self.middlePlayButton.hidden = YES;
    if (![self.videoURL.scheme isEqualToString:@"file"]) {
        [self.videoLoadingIndicator startAnimating];
    }
}



- (void)destroyPlayer {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    if (_player) {
        [_player pause];
        [_player removeTimeObserver:_playbackTimeObserver];
        [_playerItem removeObserver:self forKeyPath:@"status"];
        [_playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
        [_playerItem removeObserver:self forKeyPath:@"playbackBufferEmpty"];
        [_playerItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"];
        _player = nil;
        _playerItem = nil;
        _playbackTimeObserver = nil;
        _playerLayerView.hidden = YES;
    }
}

- (void)applicationWillResignActive {
    if (!_playerItem) {
        return;
    }
    [self pauseVideo];
}

- (void)applicationDidBecomeActive {
    // 重新回到前台
}

#pragma -mark  播放设置相关
- (void)switchWithVideoURL:(NSURL *)videoURL
{
    if (videoURL && ![videoURL.absoluteString isEqualToString:_videoURL.absoluteString]) {
        _videoURL = videoURL;
        [self destroyPlayer];
        [self configTheSubViewsHidenOrShow];
    }
}

#pragma -mark 监控播放 KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    AVPlayerItem *playerItem = (AVPlayerItem *)object;
    if ([keyPath isEqualToString:@"status"]) {
        switch (playerItem.status) {
            case AVPlayerStatusReadyToPlay:
            {
//                NSLog(@"AVPlayerStatusReadyToPlay");
                dispatch_async(dispatch_get_main_queue(), ^{
                    _isVideoCanPlay = YES;
                    _videoDuration = playerItem.duration.value * 1.0 / playerItem.duration.timescale; // total time of the video
                    _currentPlayTime = 0;
                    [self.bottomBar showStartWithVideoDuration:_videoDuration];
                    [self playVideo];
                    
//                    WS(weakSelf);
                    // 监控视频播放进度
//                    CMTime interval = CMTimeMakeWithSeconds(0.02, NSEC_PER_SEC);
//                    _playbackTimeObserver = [_player addPeriodicTimeObserverForInterval:interval queue:NULL usingBlock:^(CMTime time) {
//                        __strong __typeof(weakSelf)strongSelf = weakSelf;
//                        if (strongSelf.isDragingSlider) {
//                            return;
//                        }
//                        CGFloat currentTime = CMTimeGetSeconds(playerItem.currentTime);
//                        if (currentTime > strongSelf.videoDuration) {
//                            currentTime = strongSelf.videoDuration;
//                        }
//                        if (currentTime < strongSelf.currentPlayTime) {
//                            currentTime = strongSelf.currentPlayTime;
//                        }else {
//                            strongSelf.currentPlayTime = currentTime;
//                        }
////                        NSLog(@"当前播放视频的进度条值： %lf",currentTime);
//                        [strongSelf.bottomBar showProgressWithCurrentVideoTime:currentTime];
//                    }];
                });
                break;
            }
            case AVPlayerStatusFailed:
            case AVPlayerStatusUnknown:
            {
            
                dispatch_async(dispatch_get_main_queue(), ^{
                    _isVideoCanPlay = NO;
                    [self.videoLoadingIndicator stopAnimating];
                    self.playerState = MSVideoPlayerStateFailed;
                    self.middlePlayButton.hidden = NO;
                    [self destroyPlayer];
//                    [MSProgressHUD showToast:@"视频无法播放，请稍后重试"];
                });
                break;
            }
        }
    }else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
//        CMTimeRange timeRange = [playerItem.loadedTimeRanges.firstObject CMTimeRangeValue]; // buffer area
//        NSTimeInterval timeBuffered = CMTimeGetSeconds(timeRange.start) + CMTimeGetSeconds(timeRange.duration); // buffer progress
//        NSTimeInterval timeTotal = CMTimeGetSeconds(playerItem.duration);
//        //播放条缓存进度
//        [self.bottomBar.cacheProgressView setProgress:timeBuffered / timeTotal animated:YES];
    } else if ([keyPath isEqualToString:@"playbackBufferEmpty"]) { //监听播放器在缓冲数据的状态
        if (self.playerItem.playbackBufferEmpty) {
            [self.videoLoadingIndicator startAnimating];
//            NSLog(@"playbackBufferEmpty缓冲不足暂停了");
        }
    } else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) {
        if (self.playerItem.playbackLikelyToKeepUp) {
            [self.videoLoadingIndicator stopAnimating];
//            NSLog(@"缓冲达到可播放程度了");
        }
    }
}

- (void)playerItemDidPlayToEnd:(NSNotification *)notification {
    // 播放完就进入暂停状态
    self.playerState = MSVideoPlayerStatePaused;
    [_player seekToTime:kCMTimeZero];
    _currentPlayTime = 0;
    [self.bottomBar divideThePlayPauseButtonWithPlayStatus:NO];
    if (_loopPlayVideo) {
        [self playVideo];
    }else {
        self.middlePlayButton.hidden = NO;
//        [self hideBottomAndTopTool];
    }
}

#pragma mark - 播放控制的各类方法
- (void)setPlayerState:(MSVideoPlayerState)playerState
{
    _playerState = playerState;
}

- (void)pauseVideo{
    if (!_playerItem) {
        return;
    }
    [_player pause];
    self.playerState = MSVideoPlayerStatePaused;
    self.middlePlayButton.hidden = NO;
    [self.videoLoadingIndicator stopAnimating];
    [self.bottomBar divideThePlayPauseButtonWithPlayStatus:NO];
    if ([self.delegate respondsToSelector:@selector(videoPlayerDidPause:)]) {
        [self.delegate videoPlayerDidPause:self];
    }
}

- (void)playVideo{
    if (!_playerItem) {
        return;
    }
    self.playerState = MSVideoPlayerStatePlaying;
    self.middlePlayButton.hidden = YES;
    [self.bottomBar divideThePlayPauseButtonWithPlayStatus:YES];
//    WS(weakself);
//    if (!weakself.playerItem.isPlaybackLikelyToKeepUp && ![weakself.videoURL.scheme isEqualToString:@"file"] ){
//        [weakself.videoLoadingIndicator startAnimating];
//    }
    [_player play];
    if ([self.delegate respondsToSelector:@selector(videoPlayerDidPlay:)]) {
        [self.delegate videoPlayerDidPlay:self];
    }
}

#pragma -mark 点击事件
- (void)touchViewTapAction:(UITapGestureRecognizer *)tap {
//    if (self.tMSarView.hidden) {
        [self showBottomAndTopTool];
//    } else {
//        [self hideBottomAndTopTool];
//    }
}

// 点击左上角取消事件
- (void)cancelTheVideo {
    if ([self.delegate respondsToSelector:@selector(videoPlayerRemove:)]) {
        [self.delegate videoPlayerRemove:self];
    }else {
        [self removeTheVideoPlayer];
    }
}

- (void)removeTheVideoPlayer
{
    [self destroyPlayer];
//    [self removeAllSubviews];
    [self removeFromSuperview];
}

/// 右上角下载按钮
- (void)downloadTheVideo {
    if ([self.delegate respondsToSelector:@selector(videoPlayerDownload:)]) {
        [self.delegate videoPlayerDownload:self];
    }
}

- (void)repeatPlayButtonClick
{
    if (self.playerState == MSVideoPlayerStateFailed) {
        [self setupPlayer];
    }else {
        [self playVideo];
    }
}

#pragma mark - SRVideoBottomBarDelegate
- (void)videoBottomBarDidClickPlayPauseBtn {
    switch (self.playerState) {
        case MSVideoPlayerStatePlaying:
            if (!_playerItem) {
                return;
            }
//            NSLog(@"---------------点击了按钮-----暂停");
            [self pauseVideo];
            break;
        case MSVideoPlayerStatePaused:
            if (!_playerItem) {
                return;
            }
//            NSLog(@"---------------点击了按钮-----播放");
            [self playVideo];
            break;
        case MSVideoPlayerStateFailed:
            self.middlePlayButton.hidden = YES;
            [self setupPlayer];
//            NSLog(@"---------------点击了按钮-----重新加载");
            break;
//        case MSVideoPlayerStateBuffering:
//            return;
        default:
            break;
    }
    [self timingHideTMSottomBar];
}


/// 设置是否静音播放
/// @param muted muted description
- (void)videoBottomBarDidClickMuted:(BOOL)muted {
    self.player.muted = muted;
}

- (void)videoBottomBarChangingSlider:(UISlider *)slider {
    if (!_isDragingSlider) {
        if (self.playerState == MSVideoPlayerStatePlaying) {
            _previousSeekPlayStatus = YES;
        }else {
            _previousSeekPlayStatus = NO;
        }
    }
    _isDragingSlider = YES;
    _currentPlayTime = slider.value;
    [self seekToTimeWithSeconds:slider.value];
    [self pauseVideo];
}

- (void)videoBottomBarDidEndChangeSlider:(UISlider *)slider {
    _isDragingSlider = NO;
    _currentPlayTime = slider.value;
    [self seekToTimeWithSeconds:slider.value];
    if (_previousSeekPlayStatus) {
        [self playVideo];
    }
}

#pragma mark - Assist Methods
- (void)seekToTimeWithSeconds:(CGFloat)seconds {
    seconds = MAX(0, seconds);
    seconds = MIN(seconds, _videoDuration);
    [self.player seekToTime:CMTimeMakeWithSeconds(seconds , NSEC_PER_SEC) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
}

- (void)showBottomAndTopTool {
    if (!_loopPlayVideo) {
        self.tMSarView.hidden = NO;
        if (_isVideoCanPlay) {
            self.bottomBar.hidden = NO;
        }
        [self timingHideTMSottomBar];
    }
}

- (void)hideBottomAndTopTool {
    self.bottomBar.hidden = YES;
    self.tMSarView.hidden = YES;
}

- (void)timingHideTMSottomBar {
//    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideTMSottomBar) object:nil];
//    [self performSelector:@selector(hideTMSottomBar) withObject:nil afterDelay:5.0];
}

#pragma -mark MSVideoHelperDownloadDelegate   下载视频相关代理
- (void)startDownloadTheVideoWithURLString:(NSString *)urlString {
    // 当前播放的正是 下载的就显示
    if ([urlString isEqualToString:_videoURL.absoluteString]) {
        self.downloadProgress.hidden = NO;
        self.middlePlayButton.hidden = YES;
    }
}

- (void)continueDownloadTheVideoWithURLString:(NSString *)urlString andProgress:(CGFloat)progress {
    if ([urlString isEqualToString:_videoURL.absoluteString]) {
        self.downloadProgress.hidden = NO;
        self.downloadProgress.progress = progress;
        self.middlePlayButton.hidden = YES;
    }
}

- (void)endDownloadTheVideoWithURLString:(NSString *)urlString andLocalVideoPath:(NSString *)videoPath {
    if ([urlString isEqualToString:_videoURL.absoluteString]) {
        self.downloadProgress.hidden = YES;
        if ([[NSFileManager defaultManager] fileExistsAtPath:videoPath]) {
            [self setVideoURL:[NSURL fileURLWithPath:videoPath]];
        }
    }
}



@end


